#include "stdafx.h"
#include "SendRequestThread.h"

#include "Thread/AbstractApiConnection.h"
#include "Utils/FastBlockQueue.h"
#include "Business/Cancellation.h"
#include "Business/Dealing.h"
#include "Utils/TimeoutNotifier.h"
#include "Business/RequestTimeoutCallback.h"
#include "Business/RequestTimeout.h"


using namespace std;

SendRequestThread::SendRequestThread(
	TimeoutNotifier& timeoutNotifier,
	FastBlockQueue& requestQueue,
	FastBlockQueue& responseQueue,
	AbstractApiConnection& apiConnection)
:m_timeoutNotifier(timeoutNotifier),
m_requestQueue(requestQueue),
m_responseQueue(responseQueue),
m_apiConnection(apiConnection)
{
}

SendRequestThread::~SendRequestThread()
{
}

void SendRequestThread::Run()
{
	m_apiConnection.Init();
	const int TIMEOUT = 300; //100ms
	bool quitFlag = false;
	while (!quitFlag)
	{
		QueueItem& item = m_requestQueue.Pop(quitFlag);

		if (quitFlag) break;

		switch (item.type)
		{
		case QueueItem::ORDER:
			{
				Dealing const& dealing = *(Dealing*)item.data;
				RequestTimeout requestTimeout(dealing.GetBusiness(),dealing.GetContract(),
					dealing.GetLocalId(),RequestTimeout::ORDER);
				m_timeoutNotifier.AddTimeout(TIMEOUT,CallbackablePtr(new RequestTimeoutCallback(requestTimeout,m_responseQueue)));
				m_apiConnection.SendOrder(dealing);
			}
			break;
		case QueueItem::CANCELLATION:
			{
				Cancellation const& cancellation = *(Cancellation*)item.data;
				RequestTimeout requestTimeout(cancellation.GetBusiness(),cancellation.GetContract(),
					cancellation.GetCancelLocalId(),RequestTimeout::CANCEL);
				m_timeoutNotifier.AddTimeout(TIMEOUT,CallbackablePtr(new RequestTimeoutCallback(requestTimeout,m_responseQueue)));
				m_apiConnection.SendCancellation(cancellation);
			}
			break;
		case QueueItem::CONTRACT:
			{
				char const* code = item.data;
				if (m_subscribedMarkets.find(code) == m_subscribedMarkets.end())
				{
					m_subscribedMarkets[code] = 0;
					m_apiConnection.SubscribeMarket(code);
				}
			}
			break;
		case QueueItem::QUERY_MBL:
			{
				char const* code = item.data;
				m_apiConnection.QueryMblMarket(code);
			}
			break;
		case QueueItem::PENDING_CONTRACT:
			{
				char const* code = item.data;
				if (m_subscribedPendingMarkets.find(code) == m_subscribedPendingMarkets.end())
				{
					m_subscribedPendingMarkets[code] = 0;
					m_apiConnection.SubscribePendingMarket(code);
				}
			}
			break;
		default:
			break;
		}
	}
	m_apiConnection.Release();
}

